/** ***********************************************************************************
* @file         com_lib.c
* @brief        系统公共函数
* @details      主要是定义了在系统中使用的公共函数 主要包含数据类型、格式的转换、MD5、校验、算法、字符比较等函数接口
* @author       杨小珛
* @date         2013/04/03
* @copyright    北京高知科技有限公司    
* @version      V1.0
* @attention    函数注释不进行描述
**************************************************************************************/
#include "com_lib.h"

/*-------------------------------------------------------------------------
        全局变量定义(Global variable definition)
  -----------------------------------------------------------------------*/
#define F(x,y,z) (((x)&(y))|((~x)&(z)))
#define G(x,y,z) (((x)&(z))|((y)&(~z)))
#define H(x,y,z) ((x)^(y)^(z))
#define I(x,y,z) ((y)^((x)|(~z)))
#define ROTATE_LEFT(x,n) ((x << n) | (x >> (32-n)))
#define FF(a, b, c, d, x, s, ac) {(a) += F((b),(c),(d))+(x)+(ac); (a)=ROTATE_LEFT((a),(s)); (a)+=(b);}
#define GG(a, b, c, d, x, s, ac) {(a) += G((b),(c),(d))+(x)+(ac); (a)=ROTATE_LEFT((a),(s)); (a)+=(b);}
#define HH(a, b, c, d, x, s, ac) {(a) += H((b),(c),(d))+(x)+(ac); (a)=ROTATE_LEFT((a),(s)); (a)+=(b);}
#define II(a, b, c, d, x, s, ac) {(a) += I((b),(c),(d))+(x)+(ac); (a)=ROTATE_LEFT((a),(s)); (a)+=(b);}

typedef struct{
	uint32_t  count[2];
	uint32_t  state[4];
	uint8_t buffer[64];
}MD5_CTX;

uint8_t PADDING[]={0x80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};


static const uint32_t crc32c_table[256] = {
	0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L,
	0xC79A971FL, 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL,
	0x8AD958CFL, 0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL,
	0x4D43CFD0L, 0xBF284CD3L, 0xAC78BF27L, 0x5E133C24L,
	0x105EC76FL, 0xE235446CL, 0xF165B798L, 0x030E349BL,
	0xD7C45070L, 0x25AFD373L, 0x36FF2087L, 0xC494A384L,
	0x9A879FA0L, 0x68EC1CA3L, 0x7BBCEF57L, 0x89D76C54L,
	0x5D1D08BFL, 0xAF768BBCL, 0xBC267848L, 0x4E4DFB4BL,
	0x20BD8EDEL, 0xD2D60DDDL, 0xC186FE29L, 0x33ED7D2AL,
	0xE72719C1L, 0x154C9AC2L, 0x061C6936L, 0xF477EA35L,
	0xAA64D611L, 0x580F5512L, 0x4B5FA6E6L, 0xB93425E5L,
	0x6DFE410EL, 0x9F95C20DL, 0x8CC531F9L, 0x7EAEB2FAL,
	0x30E349B1L, 0xC288CAB2L, 0xD1D83946L, 0x23B3BA45L,
	0xF779DEAEL, 0x05125DADL, 0x1642AE59L, 0xE4292D5AL,
	0xBA3A117EL, 0x4851927DL, 0x5B016189L, 0xA96AE28AL,
	0x7DA08661L, 0x8FCB0562L, 0x9C9BF696L, 0x6EF07595L,
	0x417B1DBCL, 0xB3109EBFL, 0xA0406D4BL, 0x522BEE48L,
	0x86E18AA3L, 0x748A09A0L, 0x67DAFA54L, 0x95B17957L,
	0xCBA24573L, 0x39C9C670L, 0x2A993584L, 0xD8F2B687L,
	0x0C38D26CL, 0xFE53516FL, 0xED03A29BL, 0x1F682198L,
	0x5125DAD3L, 0xA34E59D0L, 0xB01EAA24L, 0x42752927L,
	0x96BF4DCCL, 0x64D4CECFL, 0x77843D3BL, 0x85EFBE38L,
	0xDBFC821CL, 0x2997011FL, 0x3AC7F2EBL, 0xC8AC71E8L,
	0x1C661503L, 0xEE0D9600L, 0xFD5D65F4L, 0x0F36E6F7L,
	0x61C69362L, 0x93AD1061L, 0x80FDE395L, 0x72966096L,
	0xA65C047DL, 0x5437877EL, 0x4767748AL, 0xB50CF789L,
	0xEB1FCBADL, 0x197448AEL, 0x0A24BB5AL, 0xF84F3859L,
	0x2C855CB2L, 0xDEEEDFB1L, 0xCDBE2C45L, 0x3FD5AF46L,
	0x7198540DL, 0x83F3D70EL, 0x90A324FAL, 0x62C8A7F9L,
	0xB602C312L, 0x44694011L, 0x5739B3E5L, 0xA55230E6L,
	0xFB410CC2L, 0x092A8FC1L, 0x1A7A7C35L, 0xE811FF36L,
	0x3CDB9BDDL, 0xCEB018DEL, 0xDDE0EB2AL, 0x2F8B6829L,
	0x82F63B78L, 0x709DB87BL, 0x63CD4B8FL, 0x91A6C88CL,
	0x456CAC67L, 0xB7072F64L, 0xA457DC90L, 0x563C5F93L,
	0x082F63B7L, 0xFA44E0B4L, 0xE9141340L, 0x1B7F9043L,
	0xCFB5F4A8L, 0x3DDE77ABL, 0x2E8E845FL, 0xDCE5075CL,
	0x92A8FC17L, 0x60C37F14L, 0x73938CE0L, 0x81F80FE3L,
	0x55326B08L, 0xA759E80BL, 0xB4091BFFL, 0x466298FCL,
	0x1871A4D8L, 0xEA1A27DBL, 0xF94AD42FL, 0x0B21572CL,
	0xDFEB33C7L, 0x2D80B0C4L, 0x3ED04330L, 0xCCBBC033L,
	0xA24BB5A6L, 0x502036A5L, 0x4370C551L, 0xB11B4652L,
	0x65D122B9L, 0x97BAA1BAL, 0x84EA524EL, 0x7681D14DL,
	0x2892ED69L, 0xDAF96E6AL, 0xC9A99D9EL, 0x3BC21E9DL,
	0xEF087A76L, 0x1D63F975L, 0x0E330A81L, 0xFC588982L,
	0xB21572C9L, 0x407EF1CAL, 0x532E023EL, 0xA145813DL,
	0x758FE5D6L, 0x87E466D5L, 0x94B49521L, 0x66DF1622L,
	0x38CC2A06L, 0xCAA7A905L, 0xD9F75AF1L, 0x2B9CD9F2L,
	0xFF56BD19L, 0x0D3D3E1AL, 0x1E6DCDEEL, 0xEC064EEDL,
	0xC38D26C4L, 0x31E6A5C7L, 0x22B65633L, 0xD0DDD530L,
	0x0417B1DBL, 0xF67C32D8L, 0xE52CC12CL, 0x1747422FL,
	0x49547E0BL, 0xBB3FFD08L, 0xA86F0EFCL, 0x5A048DFFL,
	0x8ECEE914L, 0x7CA56A17L, 0x6FF599E3L, 0x9D9E1AE0L,
	0xD3D3E1ABL, 0x21B862A8L, 0x32E8915CL, 0xC083125FL,
	0x144976B4L, 0xE622F5B7L, 0xF5720643L, 0x07198540L,
	0x590AB964L, 0xAB613A67L, 0xB831C993L, 0x4A5A4A90L,
	0x9E902E7BL, 0x6CFBAD78L, 0x7FAB5E8CL, 0x8DC0DD8FL,
	0xE330A81AL, 0x115B2B19L, 0x020BD8EDL, 0xF0605BEEL,
	0x24AA3F05L, 0xD6C1BC06L, 0xC5914FF2L, 0x37FACCF1L,
	0x69E9F0D5L, 0x9B8273D6L, 0x88D28022L, 0x7AB90321L,
	0xAE7367CAL, 0x5C18E4C9L, 0x4F48173DL, 0xBD23943EL,
	0xF36E6F75L, 0x0105EC76L, 0x12551F82L, 0xE03E9C81L,
	0x34F4F86AL, 0xC69F7B69L, 0xD5CF889DL, 0x27A40B9EL,
	0x79B737BAL, 0x8BDCB4B9L, 0x988C474DL, 0x6AE7C44EL,
	0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L, 0xAD7D5351L
};
 
const uint8_t crc8c_table[256]={    
  0, 94, 188, 226, 97, 63, 221, 131, 194, 156, 126, 32, 163, 253, 31, 65,    
  157, 195, 33, 127, 252, 162, 64, 30, 95, 1, 227, 189, 62, 96, 130, 220,    
  35, 125, 159, 193, 66, 28, 254, 160, 225, 191, 93, 3, 128, 222, 60, 98,    
  190, 224, 2, 92, 223, 129, 99, 61, 124, 34, 192, 158, 29, 67, 161, 255,    
  70, 24, 250, 164, 39, 121, 155, 197, 132, 218, 56, 102, 229, 187, 89, 7,    
  219, 133, 103, 57, 186, 228, 6, 88, 25, 71, 165, 251, 120, 38, 196, 154,    
  101, 59, 217, 135, 4, 90, 184, 230, 167, 249, 27, 69, 198, 152, 122, 36,    
  248, 166, 68, 26, 153, 199, 37, 123, 58, 100, 134, 216, 91, 5, 231, 185,    
  140, 210, 48, 110, 237, 179, 81, 15, 78, 16, 242, 172, 47, 113, 147, 205,    
  17, 79, 173, 243, 112, 46, 204, 146, 211, 141, 111, 49, 178, 236, 14, 80,    
  175, 241, 19, 77, 206, 144, 114, 44, 109, 51, 209, 143, 12, 82, 176, 238,    
  50, 108, 142, 208, 83, 13, 239, 177, 240, 174, 76, 18, 145, 207, 45, 115,    
  202, 148, 118, 40, 171, 245, 23, 73, 8, 86, 180, 234, 105, 55, 213, 139,    
  87, 9, 235, 181, 54, 104, 138, 212, 149, 203, 41, 119, 244, 170, 72, 22,    
  233, 183, 85, 11, 136, 214, 52, 106, 43, 117, 151, 201, 74, 20, 246, 168,    
  116, 42, 200, 150, 21, 75, 169, 247, 182, 232, 10, 84, 215, 137, 107, 53    
};    
    
    	
static void MD5Transform(uint32_t* state,  uint8_t* block);
static void MD5Encode( uint8_t* output, uint32_t  *input, uint8_t len);

static void MD5Init(MD5_CTX *context)
{
  context->count[0] = 0;
  context->count[1] = 0;
  context->state[0] = 0x67452301;
  context->state[1] = 0xEFCDAB89;
  context->state[2] = 0x98BADCFE;
  context->state[3] = 0x10325476;
}

static void MD5Update(MD5_CTX *context,  uint8_t* input, uint32_t  inputlen)
{
  uint32_t  i = 0, index = 0, partlen = 0;
  index = (context->count[0] >> 3) & 0x3F;
  partlen = 64 - index;
  context->count[0] += inputlen << 3;
  if(context->count[0] < (inputlen << 3))
	{
		context->count[1]++;
	}
  context->count[1] += inputlen >> 29;

  if(inputlen >= partlen)
  {
    memcpy(&context->buffer[index], input, partlen);
    MD5Transform(context->state, context->buffer);
    for(i = partlen;i+64 <= inputlen;i+=64)
	 	{
	 		MD5Transform(context->state,&input[i]);
	 	}
    index = 0;
  }
  else
  {
    i = 0;
  }
  memcpy(&context->buffer[index], &input[i], inputlen-i);
}

static void MD5Final(MD5_CTX *context,  uint8_t *digest)
{
  uint8_t  index = 0, padlen = 0;
  uint8_t bits[8];
  index = (context->count[0] >> 3) & 0x3F;
  padlen = (index < 56)?(56-index):(120-index);
  MD5Encode(bits, context->count, 8);
  MD5Update(context, PADDING, padlen);
  MD5Update(context, bits, 8);
  MD5Encode(digest,context->state, 16);
}

static void MD5Encode( uint8_t* output, uint32_t  *input, uint8_t len)
{
  uint8_t  i = 0, j = 0;
  while(j < len)
  {
    output[j] = input[i] & 0xFF;
    output[j+1] = (input[i] >> 8) & 0xFF;
    output[j+2] = (input[i] >> 16) & 0xFF;
    output[j+3] = (input[i] >> 24) & 0xFF;
    i++;
    j+=4;
  }
}

static void MD5Decode(uint32_t  *output,  uint8_t* input, uint8_t  len)
{
	uint8_t  i = 0, j = 0;
	while(j < len)
  {
		output[i] = (input[j]) | (input[j+1] << 8) | (input[j+2] << 16) | (input[j+3] << 24);
		i++;
		j+=4;
	}
}

static void MD5Transform(uint32_t* state,  uint8_t* block)
{
  uint32_t  a = state[0];
  uint32_t  b = state[1];
  uint32_t  c = state[2];
  uint32_t  d = state[3];
  uint32_t  x[64];
  MD5Decode(x,block,64);
  FF(a, b, c, d, x[ 0], 7,  0xd76aa478);
  FF(d, a, b, c, x[ 1], 12, 0xe8c7b756);
  FF(c, d, a, b, x[ 2], 17, 0x242070db);
  FF(b, c, d, a, x[ 3], 22, 0xc1bdceee);
  FF(a, b, c, d, x[ 4], 7,  0xf57c0faf);
  FF(d, a, b, c, x[ 5], 12, 0x4787c62a);
  FF(c, d, a, b, x[ 6], 17, 0xa8304613);
  FF(b, c, d, a, x[ 7], 22, 0xfd469501);
  FF(a, b, c, d, x[ 8], 7,  0x698098d8);
  FF(d, a, b, c, x[ 9], 12, 0x8b44f7af);
  FF(c, d, a, b, x[10], 17, 0xffff5bb1);
  FF(b, c, d, a, x[11], 22, 0x895cd7be);
  FF(a, b, c, d, x[12], 7,  0x6b901122);
  FF(d, a, b, c, x[13], 12, 0xfd987193);
  FF(c, d, a, b, x[14], 17, 0xa679438e);
  FF(b, c, d, a, x[15], 22, 0x49b40821);

  GG(a, b, c, d, x[ 1], 5,  0xf61e2562);
  GG(d, a, b, c, x[ 6], 9,  0xc040b340);
  GG(c, d, a, b, x[11], 14, 0x265e5a51);
  GG(b, c, d, a, x[ 0], 20, 0xe9b6c7aa);
  GG(a, b, c, d, x[ 5], 5,  0xd62f105d);
  GG(d, a, b, c, x[10], 9,  0x2441453);
  GG(c, d, a, b, x[15], 14, 0xd8a1e681);
  GG(b, c, d, a, x[ 4], 20, 0xe7d3fbc8);
  GG(a, b, c, d, x[ 9], 5,  0x21e1cde6);
  GG(d, a, b, c, x[14], 9,  0xc33707d6);
  GG(c, d, a, b, x[ 3], 14, 0xf4d50d87);
  GG(b, c, d, a, x[ 8], 20, 0x455a14ed);
  GG(a, b, c, d, x[13], 5,  0xa9e3e905);
  GG(d, a, b, c, x[ 2], 9,  0xfcefa3f8);
  GG(c, d, a, b, x[ 7], 14, 0x676f02d9);
  GG(b, c, d, a, x[12], 20, 0x8d2a4c8a);

  HH(a, b, c, d, x[ 5], 4,  0xfffa3942);
  HH(d, a, b, c, x[ 8], 11, 0x8771f681);
  HH(c, d, a, b, x[11], 16, 0x6d9d6122);
  HH(b, c, d, a, x[14], 23, 0xfde5380c);
  HH(a, b, c, d, x[ 1], 4,  0xa4beea44);
  HH(d, a, b, c, x[ 4], 11, 0x4bdecfa9);
  HH(c, d, a, b, x[ 7], 16, 0xf6bb4b60);
  HH(b, c, d, a, x[10], 23, 0xbebfbc70);
  HH(a, b, c, d, x[13], 4,  0x289b7ec6);
  HH(d, a, b, c, x[ 0], 11, 0xeaa127fa);
  HH(c, d, a, b, x[ 3], 16, 0xd4ef3085);
  HH(b, c, d, a, x[ 6], 23, 0x4881d05);
  HH(a, b, c, d, x[ 9], 4,  0xd9d4d039);
  HH(d, a, b, c, x[12], 11, 0xe6db99e5);
  HH(c, d, a, b, x[15], 16, 0x1fa27cf8);
  HH(b, c, d, a, x[ 2], 23, 0xc4ac5665);

  II(a, b, c, d, x[ 0], 6,  0xf4292244);
  II(d, a, b, c, x[ 7], 10, 0x432aff97);
  II(c, d, a, b, x[14], 15, 0xab9423a7);
  II(b, c, d, a, x[ 5], 21, 0xfc93a039);
  II(a, b, c, d, x[12], 6,  0x655b59c3);
  II(d, a, b, c, x[ 3], 10, 0x8f0ccc92);
  II(c, d, a, b, x[10], 15, 0xffeff47d);
  II(b, c, d, a, x[ 1], 21, 0x85845dd1);
  II(a, b, c, d, x[ 8], 6,  0x6fa87e4f);
  II(d, a, b, c, x[15], 10, 0xfe2ce6e0);
  II(c, d, a, b, x[ 6], 15, 0xa3014314);
  II(b, c, d, a, x[13], 21, 0x4e0811a1);
  II(a, b, c, d, x[ 4], 6,  0xf7537e82);
  II(d, a, b, c, x[11], 10, 0xbd3af235);
  II(c, d, a, b, x[ 2], 15, 0x2ad7d2bb);
  II(b, c, d, a, x[ 9], 21, 0xeb86d391);

  state[0] += a;
  state[1] += b;
  state[2] += c;
  state[3] += d;
}


void MD5Digest(uint8_t* pszInput, uint8_t nInputSize, uint8_t* pszOutPut)
{
	MD5_CTX context;
	MD5Init(&context);
	MD5Update(&context, pszInput, nInputSize);
	MD5Final(&context, pszOutPut);
}

/*******************************************************************************
* 名称:   exp10
* 功能:   10的n次方
* 参数:
           n:    n次方
* 返回值:
           幂的结果
* 说明:
           注意n <= 9;
*******************************************************************************/
int mexp10( int n )
{
    int i, sum = 0;

    if( n >= 10 )  return 0;

    if( n == 0 )   return 1;

    for( i = 1; i < n; i++ )
    {
        sum *= 10;
    }
	
    return sum;
}

// -----------------------------------------------------------------------------------------

uint16_t REV_U16( const uint16_t s )
{
    return ( uint16_t )(( s << 8 ) + ( s >> 8 ) );
}

uint32_t REV_U32( const uint32_t s )
{
    uint8_t d[4];
    d[3] = s & 0xFF;
    d[2] = ( s & 0xFF00 ) >> 8;
    d[1] = ( s & 0xFF0000 ) >> 16;
    d[0] = ( s & 0xFF000000 ) >> 24;
    return *(( uint32_t* )d );
}

/********************************************************************************
* 函数名称 ：uint8_t check_calc_xor(uint8_t* Data,uint16_t DateLen)
* 函数功能 ：计算异或值
* 参    数 ：Data:数据指针  DateLen 数据长度
* 返 回 值 ：异或结果
* 注    意 ：无
********************************************************************************/
uint8_t check_calc_xor( const char* Data, uint16_t DateLen )
{
    volatile uint8_t chk_sum = 0;
	
    while( DateLen-- )
    {
        chk_sum ^= *( Data++ );
    }
	
    return chk_sum;
}

/********************************************************************************
* 函数名称 ：uint8_t check_calc_xor(uint8_t* Data,uint16_t DateLen)
* 函数功能 ：异或校验函数
* 参    数 ：pu8Data:数据指针  u8Len 数据长度
* 返 回 值 ：异或结果
* 注    意 ：无
********************************************************************************/
uint8_t calc_check_sum(uint8_t* pu8Data, uint8_t u8Len)
{   
	uint8_t  i = 1;    
	uint8_t  result = 0;    
	if ((pu8Data == NULL) || (u8Len == 0))    
	{    
		return 0;    
	}   
	result = pu8Data[0];    
	for (; i < u8Len; i++ )   
	{        
		result ^= pu8Data[i];    
	}    
	return result;
}
/*******************************************************************************
** 函数:	check_calc_acc
** 功能：	累加和校验
** 参数:
			p:      源数据指针
**			len:    源数据长度
**
** 返回值：
**			校验值
* 说明：
*******************************************************************************/
uint16_t check_calc_acc( const char* p, uint32_t len )
{
    uint16_t chk_sum = 0;
	
    while( len-- )
        chk_sum += *( p++ );
    
    return chk_sum;
}


/********************************************************************************
* 函数名称 ：CRC16Caculate
* 函数功能 ：计算CRC16的校验和 半字计算法
* 参    数 ：AP:要计算的数据指针  LEN：数据长度  CRC16_Type：标准  自定义
* 返 回 值 ：无
* 注    意 ：无
********************************************************************************/
uint16_t  check_calc_crc16( const char *AP, uint16_t LEN, uint16_t CRC16_Type )
{
    uint16_t  CRC16;
    uint16_t  i;
    uint8_t  CRC_H4;
    uint16_t const CRCTable[16] = {0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
                                   0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF
                                  };
    CRC16 = 0xFFFF - CRC16_Type;

    for( i = 0; i < LEN; i++ )
    {
        CRC_H4 = ( uint8_t )( CRC16 >> 12 );
        CRC16 = CRC16 << 4;
        CRC16 = CRC16 ^ CRCTable[CRC_H4 ^( *AP >> 4 )];
        CRC_H4 = ( uint8_t )( CRC16 >> 12 );
        CRC16 = CRC16 << 4;
        CRC16 = CRC16 ^ CRCTable[CRC_H4 ^( *AP & 0x0F )];
        AP++;
    }

    return CRC16;
}


/****************************************************************************/
char *strnchar( const char * s, int c, unsigned int num )
{
    unsigned int l = 0;

    char *p = ( char* )s;

    if(( NULL == p ) || ( 0 == num ) )
        return NULL;

    while( *p && ( NULL != ( p = strchr( p, c ) ) ) )
    {
        if( ++l == num )
            return p;

        p++;
    }

    return NULL;
}
#if 1
/*******************************************************************************
* 名称:        str_to_int_precision
* 功能:        字符串转整数，带精度控制
* 参数:
            pStr:        字符串指针
            len:        字符串长度
            precision:    精度因子
* 返回值:
            转换后的整数
* 说明:
            转换后的整数，为原字符串转得的整数乘以10^precision，包括小数位
            在精度范围内的数值，并且将丢弃的小数四舍五入。
            如：    36.32569     精度万分位 --> 363257
                    1234.5       精度百分位 --> 123450
                    6789         精度十分位 --> 67890
*******************************************************************************/
int str_to_int_precision( unsigned char *pStr, unsigned char len, unsigned char precision )
{
    unsigned char i, j, k = 0;
    int d;

    unsigned char *p;

    p = (unsigned char *)memchr( pStr, '.', len );

    if( p == NULL )
    {
        p = ( unsigned char * )pStr;

        if( precision >= len )
        {
            precision -= len;
        }
        else
        {
            if( p[precision] >= '5' && p[precision] <= '9' )
                k = 1;

            p[precision] = '\0';
            precision = 0;
        }
    }
    else
    {

        i = p - pStr;
        j = i;
        i = len - i - 1;

        if( i > precision )  i = precision;
	 	 	
        precision -= i;
        i += j;
        p = ( unsigned char * )pStr;

        while( j < i )
        {
            p[j] = p[j + 1];
            j++;
        }

        p[j++] = '\0';

        if( p[j] >= '5' && p[j] <= '9' )  k = 1;
    }

    d = atoi( (const char *)p );
	
    // 精度控制
    if( precision )  d *= mexp10( precision );
	
    // 四舍五入
    if( 1 == k )  d++;

    return d;
}
#endif
/*******************************************************************************
* 名称：    char * str_start_with(const char *psrc, const char *prefix, uint32_t limit_cnt)
* 功能：    检查字符串是否以另一字符串开头
** 参数:
			psrc:       源字符串指针
**			prefix:     需要查找的字符
            limit_cnt:  指定比较字符总数
**
** 返回值：
            成功：字符串首地址
            失败：空指针
* 说明：	只适合在字符串出现在开头的查找，
*           实现思路：先找到一个字符的开始的位置然后再比较字符串
*******************************************************************************/
char * str_start_with( const char *psrc, const char *prefix, uint32_t limit_cnt )
{
    char *p = ( char* )psrc;
    uint32_t tmp;

    if( NULL == ( p = memchr( p, ( int ) * prefix, limit_cnt ) ) )
        return NULL;

    tmp = strlen( prefix );

    if( tmp > limit_cnt )
        tmp = limit_cnt;

    if( memcmp( p, prefix, tmp ) == 0 )
        return p;

    return NULL;
}

/*******************************************************************************
* 名称：    char * byte_stream_match(const char *psrc, uint32_t s_len, const char *pmatch, uint32_t m_len)
* 功能：    检查字符流是否包含指定另一字符流
** 参数:
			psrc:       源字符串指针
**			prefix:     需要查找的字符
            limit_cnt:  指定比较字符总数
**
** 返回值：
            成功：字符串首地址
            失败：空指针
* 说明：
*******************************************************************************/
const char * byte_stream_match( const char *psrc, uint32_t s_len, const char *pmatch, uint32_t m_len )
{
    const char *p1 = psrc;
    const char *p;

    while( s_len >= m_len )
    {
        if( NULL == ( p = memchr( p1, ( int ) * pmatch, s_len ) ) )
            return NULL;

        if( memcmp( p, pmatch, m_len ) == 0 )
            return p;

        p++;
        s_len -= p - p1;
        p1 = p;
    }

    return NULL;
}

/*******************************************************************************
* 名称：    uint32_t Str_To_HEX(uint8_t *pstr)
* 功能：    字符串转换为16进制
* 参数：    无
* 返回值：  无
* 说明：
*******************************************************************************/
uint32_t Str_To_HEX( uint8_t *pStr, uint16_t num )
{
    uint8_t temp[12];
    memset( temp, '\0', 12 );

    if( num == 0 )  return 0;

    if( num > 11 )  num = 11;

    memcpy( temp, pStr, num );
    return ( strtol(( const char * )temp, NULL, 10 ) );
}
#if 0
/*******************************************************************************
* 名称：    IP_Str_To_HEX
* 功能：    字符串IP地址转换为16进制
* 参数：    无
* 返回值：  无
* 说明：
*******************************************************************************/
void IP_Str_To_HEX( uint8_t* pHex, uint8_t* pStr )
{
    uint32_t i, len;
    uint8_t* p1 = NULL;
    uint8_t* p2 = pHex;

    len = strlen(( const char* )pStr );
    i = 0;

    while( len )
    {
        if( i < 4 )
        {
            if( i < 3 )
                p1 = memchr( pStr, '.', len );
            else
                p1 = memchr( pStr, ',', len );

            *p2++ = atoi(( const char* )pStr );
            *p1++;
            len -= ( p1 - pStr );
        }
        else
        {
            *(( uint16_t* )p2 ) = atoi(( const char* )pStr );
            p2 += 2;
        }

        i++;
        pStr = p1;

        if( *pStr == '\0' || i >= 5 )
            break;
    }

    if( i < 3 )   p2 = pHex;

    *p2 = '\0';
}

#endif
/*******************************************************************************
** 函数:	AsciiToHex
** 功能：	字符串转换到HEX
** 参数:
			asc:    ASCII字符
**
** 返回值：
**			HEX值
* 说明：
*******************************************************************************/
int AsciiToHex( unsigned int asc )
{
    if( asc <= '9' )
        return ( asc - '0' );
    else if( asc >= 'A' && asc <= 'F' )
        return ( asc - '7' );
    else if( asc >= 'a' && asc <= 'f' )
        return ( asc - 'W' );
    else
        return -1;
}

/*******************************************************************************
** 函数:	AsciiStringToHex
** 功能：	ASCII字符串转换为HEX数据
** 参数:
			mode:       对齐模式
			pHex:       目标HEX数据指针
**			pStr:       源数据指针
			ulLen:      源数据长度(此长度实际是目标数据长度)
**
** 返回值：
**			目标字符串长度
* 说明：
            4F60597D0041 -> 0x4F 0x60 0x59 0x7D 0x00 0x41
*******************************************************************************/
unsigned int AsciiStringToHex( unsigned int mode, char* pHex, const char* pStr, unsigned int ulLen )
{
    unsigned int i = 0, len;

    len = ulLen;

    if(( ulLen & 0x01 ) && ( mode == ALIGN_MODE_SUFFIX ) )
    {
        *pHex++ = AsciiToHex( pStr[0] );
        pStr++;
        len++;
        i++;
    }

    len = len >> 1;

    for( ; i < len; i++ )
    {
        *pHex++ = ( AsciiToHex( pStr[0] ) << 4 ) + AsciiToHex( pStr[1] );
        pStr += 2;
    }

    if(( ulLen & 0x01 ) && ( mode == ALIGN_MODE_PREFIX ) )
    {
        *pHex++ = AsciiToHex( pStr[0] );
        i++;
    }

    // 输出字符串加个结束符
    *pHex = '\0';

    return ( i );
}

/*******************************************************************************
** 函数:	Ucs2AsciiStringToHex
** 功能：	UCS2格式ASCII字符串转换为HEX数据
** 参数:
			pHex:       目标HEX数据指针
**			pUcs2:      源UCS2数据指针
			ulLen:      源数据长度(此长度实际是目标数据长度)
**
** 返回值：
**			目标字符串长度
* 说明：
            004F00600059007D00000041 -> 0x4F 0x60 0x59 0x7D 0x00 0x41
*******************************************************************************/
unsigned int Ucs2AsciiStringToHex( char* pHex, const char* pUcs2, unsigned int ulLen )
{
    unsigned int i;
	
    for( i = 2; i < ulLen; i += 4 )
        * pHex++ = ( AsciiToHex( pUcs2[i] ) << 4 ) + AsciiToHex( pUcs2[i + 1] );

    // 输出字符串加个结束符
    *pHex = '\0';
	
    return ( i >> 2 );
}

/*******************************************************************************
* 名称：    str_find_char_num(const char *psrc, const char TheChar, uint32_t limit_cnt)
* 功能：    检查字符串包含字符数量
** 参数:
			psrc:       源字符串指针
**			TheChar:    需要查找的字符
            limit_cnt:  指定比较字符总数
**
** 返回值：
            成功：字符串首地址
            失败：空指针
* 说明：
*******************************************************************************/
uint32_t  str_find_char_num( const char *psrc, const char TheChar, uint32_t limit_cnt )
{
    uint32_t CharNum = 0, i;

    if(( psrc == NULL ) || ( limit_cnt == 0 ) )
        return CharNum;

    for( i = 0; i < limit_cnt; i++, psrc++ )
    {
        if( *psrc == TheChar )
            CharNum++;
    }

    return CharNum;
}

/*******************************************************************************
** 函数:	HexToAscii
** 功能：	HEX转换到ASCII字符
** 参数:
			hex: HEX数据
**
** 返回值：
**			ASCII字符
* 说明：
*******************************************************************************/

static int HexToAscii( unsigned char hex )
{
    if( hex <= 9 )
        return ( hex + '0' );
    else if( hex >= 0xA && hex <= 0xF )
        return ( hex + '7' );
    else
        return '0';
}

/*******************************************************************************
** 函数:	HexToAsciiString
** 功能：	HEX数据转换为ASCII字符串
** 参数:
**			pStr:       目标字符串指针
			pHex:       源HEX数据指针
			ulLen:      源数据长度(此长度实际是目标数据长度)
**
** 返回值：
**			目标字符串长度
* 说明：
            0x4F 0x60 0x59 0x7D 0x00 0x41 -> 4F60597D0041
*******************************************************************************/
unsigned int HexToAsciiString( char* pStr, const char* pHex, unsigned int ulLen )
{
    unsigned int i;
	
    for( i = 0; i < ulLen; i++ )
    {
        *pStr++ = HexToAscii( pHex[i] >> 4 );
        *pStr++ = HexToAscii( pHex[i] & 0xF );
    }
    // 输出字符串加个结束符
    *pStr = '\0';
    return ( i << 1 );
}

/*******************************************************************************
** 函数:	AsciiHexToUcs2String
** 功能：	ASCII码HEX数据转换为UCS2字符串
** 参数:
			pHex:       源HEX数据指针
**			pUcs2:      目标UCS2字符串指针
			ulLen:      源数据长度(此长度实际是目标数据长度)
**
** 返回值：
**			目标字符串长度
* 说明：
            0x4F 0x60 0x59 0x7D 0x00 0x41 -> 004F00600059007D00000041
*******************************************************************************/
unsigned int AsciiHexToUcs2String( char* pUcs2, const char* pHex, unsigned int ulLen )
{
    unsigned int i;

    for( i = 0; i < ulLen; i++ )
    {
        *pUcs2++ = '0';
        *pUcs2++ = '0';
        *pUcs2++ = HexToAscii( pHex[i] >> 4 );
        *pUcs2++ = HexToAscii( pHex[i] & 0xF );
    }

    // 输出字符串加个结束符
    *pUcs2 = '\0';

    return ( i << 2 );
}


/*******************************************************************************
* 名称：    Split
* 功能：    分裂字符串
** 参数:
			arr:
**			str:
            delimiters:
**
** 返回值：无
* 说明：
*******************************************************************************/
void Split( char **arr, char *str, const char *delimiters )
{
    char *p;
    p = strtok( str, delimiters );

    while( p != NULL )
    {
        *arr++ = p;
        p = strtok( NULL, delimiters );
    }

    return;
}

/*******************************************************************************
* 名称：    mstrnlen
* 功能：    计算字符串长度
** 参数:
			psrc:       源字符串指针
            limit_cnt:  指定字符最大长度
**
** 返回值： 长度
* 说明：
*******************************************************************************/
uint32_t mstrnlen( const char *psrc, uint32_t maxlen )
{
    volatile uint32_t i;

    for( i = 0; i < maxlen; ++i )
    {
        if( psrc[i] == '\0' )
            break;
    }

    return i;
}

/*******************************************************************************
* 名称：    strnlens
* 功能：    计算指定特殊字符串长度
** 参数:
			psrc:       源字符串指针
             limit_cnt:  指定字符最大长度
**
** 返回值： 长度
* 说明：
*******************************************************************************/
uint32_t mstrnlens( const char *psrc, char ssrc ,uint32_t maxlen )
{
    volatile uint32_t i;
    for( i = 0; i < maxlen; ++i )
    {
        if( psrc[i] == ssrc )
            break;
    }
    return i;
}

/*******************************************************************************
* 名称：    char* mstrnstr( const char * src, long src_len, const char * substr, long substr_len )
* 功能：    查找指定长度数据地址
** 参数:
**
** 返回值： 长度
* 说明：
*******************************************************************************/

char* mstrnstr( const char * src, long src_len, const char * substr, long substr_len )
{
	const char * p;
	const char * pend;
	
	if(( src == NULL )||( substr == NULL ))
	{
		return NULL;
	}    	
	if( src_len < substr_len )
	{
		return NULL;
	}
	p = src;	
	pend = p + src_len ;//- substr_len;
	while ( p < pend )		
	{		
		if ( *p == *substr )			
		{
			if ( memcmp( p, substr, substr_len ) == 0)				
			{				
				return (char*)p;
			}
		}
		p++;
	}
	return NULL;	
}

/*******************************************************************************
* 名称：    char* memncpy( char * src, uint32_t src_len, char * substr , char findchar , uint32_t *clen )
* 功能：    拷贝指定位置的字符串信息
** 参数:
**
** 返回值： 长度
* 说明：
*******************************************************************************/
char* memncpy( char * src, uint32_t src_len, char * substr , char findchar , uint32_t *clen )
{
	uint32_t i = 0;
	char * p = NULL;
	if(( src == NULL ) || ( substr == NULL ))
	{
		return NULL;
	}
	for( i = 0 ; i < src_len ; i ++ )
	{
		if( *src == findchar )
		{
			break;
		}
		*substr = *src;
		substr++;
		src++;
	}
	if( i < src_len )
	{
		p = src;
	}
	if( clen != NULL )
	{
		*clen = i;
	}
	return p;
}

/*******************************************************************************
* 函数名称：bcd_time_slot_to_timestamp
* 函数功能：BCD时间段转换为时间戳
* 输    入：
            pBcd:   时间数据指针
* 输    出：
            ptimestamp: 时间戳数据指针
* 返 回 值：
            错误码
* 说    明：
*******************************************************************************/
#if 0
int bcd_time_to_timestamp( uint32_t *ptimestamp, const char* pBcd )
{
    RTC_Struct tm;

    if( pBcd[0] == 0 )
    {
        *ptimestamp = pBcd[3] * SECONDS_HOUR + pBcd[4] * SECONDS_MINUTE + pBcd[5];
    }
    else
    {
        tm.Year   = pBcd[0];
        tm.Month  = pBcd[1];
        tm.Day    = pBcd[2];
        tm.Hour   = pBcd[3];
        tm.Minute = pBcd[4];
        tm.Second = pBcd[5];
        *ptimestamp = rtc_to_count( RTC_TIM_CAL_BCD, &tm );
    }

    return ENONE;
}
#endif
/*******************************************************************************
* 函数名称：bcd_date_to_string
* 函数功能：BCD日期转换为字符串
* 输    入：
            pbcd:   时间数据指针
* 输    出：
            pstr:   字符串时间数据指针
* 返 回 值：
            数据长度
* 说    明：
*******************************************************************************/
int bcd_date_to_string( char *pstr, const char* pbcd )
{
    pstr[0] = ( pbcd[0] >> 4 ) + '0';
    pstr[1] = ( pbcd[0] & 0x0F ) + '0';
    pstr[2] = '-';
    pstr[3] = ( pbcd[1] >> 4 ) + '0';
    pstr[4] = ( pbcd[1] & 0x0F ) + '0';
    pstr[5] = '-';
    pstr[6] = ( pbcd[2] >> 4 ) + '0';
    pstr[7] = ( pbcd[2] & 0x0F ) + '0';
    pstr[8] = '\0';
    return 8;
}

/*******************************************************************************
* 函数名称：bcd_time_to_string
* 函数功能：BCD时间转换为字符串
* 输    入：
            pbcd:   时间数据指针
* 输    出：
            pstr:   字符串时间数据指针
* 返 回 值：
            数据长度
* 说    明：
*******************************************************************************/
int bcd_time_to_string( char *pstr, const char* pbcd )
{
    pstr[0] = ( pbcd[0] >> 4 ) + '0';
    pstr[1] = ( pbcd[0] & 0x0F ) + '0';
    pstr[2] = ':';
    pstr[3] = ( pbcd[1] >> 4 ) + '0';
    pstr[4] = ( pbcd[1] & 0x0F ) + '0';
    pstr[5] = ':';
    pstr[6] = ( pbcd[2] >> 4 ) + '0';
    pstr[7] = ( pbcd[2] & 0x0F ) + '0';
    pstr[8] = '\0';
    return 8;
}

/*******************************************************************************
* 函数名称：bcd_date_time_to_string
* 函数功能：BCD日期时间转换为字符串
* 输    入：
            pbcd:   时间数据指针
* 输    出：
            pstr:   字符串时间数据指针
* 返 回 值：
            数据长度
* 说    明：
*******************************************************************************/
int bcd_date_time_to_string( char *pstr, const char* pbcd )
{
    pstr[0] = ( pbcd[0] >> 4 ) + '0';
    pstr[1] = ( pbcd[0] & 0x0F ) + '0';
    pstr[2] = '-';
    pstr[3] = ( pbcd[1] >> 4 ) + '0';
    pstr[4] = ( pbcd[1] & 0x0F ) + '0';
    pstr[5] = '-';
    pstr[6] = ( pbcd[2] >> 4 ) + '0';
    pstr[7] = ( pbcd[2] & 0x0F ) + '0';
    pstr[8] = ' ';
    pstr[9] = ( pbcd[3] >> 4 ) + '0';
    pstr[10] = ( pbcd[3] & 0x0F ) + '0';
    pstr[11] = ':';
    pstr[12] = ( pbcd[4] >> 4 ) + '0';
    pstr[13] = ( pbcd[4] & 0x0F ) + '0';
    pstr[14] = ':';
    pstr[15] = ( pbcd[5] >> 4 ) + '0';
    pstr[16] = ( pbcd[5] & 0x0F ) + '0';
    pstr[17] = '\0';
    return 17;
}

/*******************************************************************************
* 函数名称：get_random_data
* 函数功能：获取随机数据
* 输    入：
* 输    出：
* 返 回 值：
* 说    明：
*******************************************************************************/
void get_random_data(uint8_t* data , uint16_t len ,uint32_t time)
{
    uint8_t h = 0;
	uint8_t i = 0;
	uint32_t sys_time = time;
	
	if(data == NULL)
	{
		return;
	}
	
	srand( ( sys_time ) );
	
	for( i = 0; i < len; i++ )
	{	
		h = rand()% 10;
		h += 0x30;
		data[i] = h;
	}	
}

/*******************************************************************************
* 函数名称：uint32_t calculate_crc32 (uint32_t crcInit,void *pStart, uint32_t uSize)
* 函数功能：计算CRC32 
* 输    入：
* 输    出：
* 返 回 值：
* 说    明：
*******************************************************************************/
uint32_t calculate_crc32 (uint32_t crcInit,void *pStart, uint32_t uSize)
{
	//#define XOROT 0xffffffffL
	uint32_t uCRCValue;
	uint8_t *pData;
 
	uCRCValue = crcInit;
	pData = (uint8_t *)pStart;
 
	while (uSize --)
	{
		uCRCValue = crc32c_table[(uCRCValue ^ *pData++) & 0xFFL] ^ (uCRCValue >> 8);
	}
 
	return uCRCValue;//uCRCValue ^ XOROT;
}

uint8_t calculate_crc8( uint8_t *p, uint16_t counter )    
{    
    unsigned char crc8 = 0;    
    
    for( counter = 0; counter > 0; counter-- )
	{    
        crc8 = crc8c_table[crc8^*p];
        p++;    
    }    
    return ( crc8 );    
}

/*******************************************************************************
* 函数名称：void array_sort (void *array, uint8_t size ,uint32_t len)
* 函数功能：
* 输    入：
* 输    出：
* 返 回 值：
* 说    明：
*******************************************************************************/
void array_sort (void *array, uint8_t size ,uint32_t len)
{
	uint32_t i, j, temp, isSorted;
	uint8_t *p_1 = NULL;
	uint16_t *p_2 = NULL;
	uint32_t *p_4 = NULL;

	if( array == NULL )
	{
		return;
	}
	if( size == 1 ) 
	{
		p_1 = (uint8_t *)array;
		for(i=0; i<len-1; i++)
		{
			isSorted = 1;  
			for(j=0; j<len-1-i; j++)
			{
				if(p_1[j] > p_1[j+1])
				{
					temp = p_1[j];
					p_1[j] = p_1[j+1];
					p_1[j+1] = temp;
					isSorted = 0;  
				}
			}
			if(isSorted) break; 
		}
	}
	else if( size == 2 ) 
	{
		p_2 = (uint16_t *)array;
		for(i=0; i<len-1; i++)
		{
			isSorted = 1;  
			for(j=0; j<len-1-i; j++)
			{
				if(p_2[j] > p_2[j+1])
				{
					temp = p_2[j];
					p_2[j] = p_2[j+1];
					p_2[j+1] = temp;
					isSorted = 0;  
				}
			}
			if(isSorted) break; 
		}
	}
	else if( size == 4 ) 
	{
		p_4 = (uint32_t *)array;
		for(i=0; i<len-1; i++)
		{
			isSorted = 1; 
			for(j=0; j<len-1-i; j++)
			{
				if(p_4[j] > p_4[j+1])
				{
					temp = p_4[j];
					p_4[j] = p_4[j+1];
					p_4[j+1] = temp;
					isSorted = 0; 
				}
			}
			if(isSorted) break;
		}
	}
}

/*******************************************************************************
* 函数名称：uint32_t calculated_absolute_value (uint32_t data1, uint32_t data2)
* 函数功能：计算绝对值
* 输    入：
* 输    出：
* 返 回 值：
* 说    明：
*******************************************************************************/
uint32_t calculated_absolute_value (uint32_t data1, uint32_t data2)
{
	uint32_t ret = 0;
	if( data1 >= data2 )
	{
		ret = data1 - data2;
	}
	else
	{
		ret = data2 - data1;
	}
	return ret;
}
/********************************************************************************
* 函数名称 ：char * get_valid_data_pointer( char * ssl , char * tcp)
* 函数功能 ：获取有效的数据指针
* 参    数 ：char * ssl SSL数据指针 char * tcp TCP数据指针
* 返 回 值 ：有效数据指针
* 注    意 ：
********************************************************************************/
char * get_valid_data_pointer( char * ssl , char * tcp)
{
	char * p = NULL ;
	
	if(( ssl == NULL ) && ( tcp == NULL ))
	{
		return NULL;
	}
	/*获取有效数据指针*/
	if(( ssl != NULL ) && ( tcp != NULL ))
	{
		if( ssl < tcp ) /*查找最小指针*/
		{
			p = ssl;
		}
		else
		{
			p = tcp;
		}
	}
	else
	{
		if( ssl != NULL )
		{
			p = ssl;
		}
		else
		{
			p = tcp;
		}
	}
	return p;
}


/**
 * 双精度浮点型数据double转字节数组（小端模式）
 */
void double_to_bytes( uint8_t *bytes, double data )
{
    uint8_t i = 0;
    uint8_t len = sizeof( double );
    uint8_t* p = (uint8_t*)&data;   //将double类型的指针强制转换为unsigned char型
    
    for( i=0; i<len; i++ )
    {
        bytes[i] = *p++;            //将相应地址中的数据保存到unsigned char数组中
    }
}

/**
 * 字节数组转双精度浮点型数据double（小端模式）
 */
double bytes_to_double( uint8_t *bytes )
{
    double data = 0;
    
    if( bytes == NULL )
    {
        return 0;    
    }
    data = *(( double *)bytes);  //直接将unsigned char型的指针强制转换为double类型
    
    return data;
}


/**
 * 双精度浮点型数据float转字节数组（小端模式）
 */
void float_to_bytes( uint8_t *bytes, float data )
{
    uint8_t i = 0;
    uint8_t len = sizeof( float );
    uint8_t* p = (uint8_t*)&data;   //将double类型的指针强制转换为unsigned char型
    
    for( i=0; i<len; i++ )
    {
        bytes[i] = *p++;            //将相应地址中的数据保存到unsigned char数组中
    }
}

/**
 * 字节数组转双精度浮点型数据float（小端模式）
 */
float bytes_to_float( uint8_t *bytes )
{
    float data = 0;
    
    if( bytes == NULL )
    {
        return 0;    
    }
    data = *(( float *)bytes);  //直接将unsigned char型的指针强制转换为double类型
    
    return data;
}


/**
 * VIN数据校验
 */
uint32_t vin_data_verification( char *Vin )
{
	uint32_t i = 0, j = 0, check = 0, ret = pdFAIL;
	char temp=0, reslt = 0;

	char jianquan[26][2] = 
	{
		{'A',1},{'B',2},{'C',3},{'D',4},{'E',5},{'F',6},
		{'G',7},{'H',8},{'I',0},{'J',1},{'K',2},{'L',3},
		{'M',4},{'N',5},{'O',0},{'P',7},{'Q',8},{'R',9},
		{'S',2},{'T',3},{'U',4},{'V',5},{'W',6},{'X',7},
		{'Y',8},{'Z',9}
	};
	char  pos[17]={8,7,6,5,4,3,2,10,0,9,8,7,6,5,4,3,2};

	for( i = 0; i < 17; i++ )
	{
		if(Vin[i]>='a'&&Vin[i]<='z') 
		{
			temp = Vin[i]-0x20;
		}
		else if((Vin[i]>='A')&&(Vin[i]<='Z'))
		{
			temp = Vin[i];
		}
		else if((Vin[i]>='0')&&(Vin[i]<='9'))
		{
			temp = Vin[i]-'0';
		}
		else 
		{
			return pdFAIL;
		}
		if((temp>='A')&&(temp<='Z'))
		{
			for(j=0;j<26;j++)
			{
				if(temp == jianquan[j][0])
				temp = jianquan[j][1];
			}
		}
		check += temp*pos[i];
	}
	reslt = check%11;
	if( reslt == 10 )
	{	
		if( Vin[8] == 'X' )
		{
			ret = pdPASS;
		}
		else
		{
			ret = pdFAIL;
		}
	}	
	else
	{
		if( reslt == ( Vin[8] - '0' ) )
		{
			ret = pdPASS;
		}
		else
		{
			ret = pdFAIL;
		}
	}

	return ret;
}

/******************************************************************************
**                            End Of File
******************************************************************************/

